home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Workbench Add-On
/
Workbench Add-On - Volume 1.iso
/
BBS-Archive
/
Comm
/
term-source.lha
/
Extras
/
Source
/
term-Source.lha
/
termTextBuffer.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-06-17
|
45KB
|
2,013 lines
/*
** termTextBuffer.c
**
** Support routines for the text buffer.
**
** Copyright © 1990-1995 by Olaf `Olsen' Barthel
** All Rights Reserved
*/
#include "termGlobal.h"
/* Gadget ID codes. */
enum { GAD_SCROLLER,GAD_UP,GAD_DOWN };
/* Menu ID codes. */
enum { MEN_SEARCH,MEN_REPEAT,MEN_GOTO,MEN_CLEARBUF_CONTENTS,MEN_QUITBUF };
/* Gadget ID codes. */
enum { GAD_STRING,GAD_LOAD,GAD_OK,GAD_CANCEL };
/* A handy macro to determine the length of a string. */
#define LINE_WIDTH(s) (s)[-1]
/* The dimensions of the scroller images. */
#define ARROW_WIDTH 18
#define ARROW_HEIGHT 11
STATIC struct NewMenu BufferMenu[] =
{
{ NM_TITLE, NULL, 0 , 0, 0, (APTR)0},
{ NM_ITEM, NULL, 0 , 0, 0, (APTR)MEN_SEARCH},
{ NM_ITEM, NULL, 0 , 0, 0, (APTR)MEN_REPEAT},
{ NM_ITEM, NM_BARLABEL, 0 , 0, 0, (APTR)0},
{ NM_ITEM, NULL, 0 , 0, 0, (APTR)MEN_GOTO},
{ NM_ITEM, NM_BARLABEL, 0 , 0, 0, (APTR)0},
{ NM_ITEM, NULL, 0 , 0, 0, (APTR)MEN_CLEARBUF_CONTENTS},
{ NM_ITEM, NM_BARLABEL, 0 , 0, 0, (APTR)0},
{ NM_ITEM, NULL, 0 , 0, 0, (APTR)MEN_QUITBUF},
{ NM_END, 0, 0 , 0, 0, (APTR)0}
};
/* Some private data (render info & window). */
STATIC struct Window *BufferWindow;
STATIC struct Screen *BufferScreen;
STATIC struct Menu *BufferMenuStrip;
STATIC BYTE BufferSignal;
STATIC struct RastPort *BPort;
STATIC APTR BufferVisualInfo;
STATIC LONG NumBufferLines,
NumBufferColumns,
LastTopLine;
STATIC struct DrawInfo *BufferDrawInfo;
STATIC struct Image *BufferAmigaGlyph,
*BufferCheckGlyph;
STATIC BYTE BufferTerminated;
STATIC WORD LocalTextFontWidth,
LocalTextFontHeight,
LocalTextFontBase;
STATIC struct TTextAttr LocalTextFont;
STATIC UBYTE __far LocalTextFontName[MAX_FILENAME_LENGTH];
STATIC struct TTextAttr LocalUserFont;
STATIC UBYTE __far LocalUserFontName[MAX_FILENAME_LENGTH];
STATIC LONG TopLine = -1,
DisplayedLines;
STATIC BYTE SearchForward = TRUE,
IgnoreCase = TRUE,
WholeWords = FALSE,
NeedClipConversion = FALSE;
STATIC struct Gadget *Scroller,
*UpArrow,
*DownArrow;
STATIC struct Image *UpImage,
*DownImage;
STATIC UWORD *BufferLineWidths,
*BufferLineOffsets,
*BufferColumnOffsets;
STATIC ULONG ArrowWidth,
ArrowHeight;
/* DeleteScroller(VOID):
*
* Delete scroller and arrow objects.
*/
STATIC VOID
DeleteScroller(VOID)
{
if(Scroller)
{
DisposeObject(Scroller);
Scroller = NULL;
}
if(UpArrow)
{
DisposeObject(UpArrow);
UpArrow = NULL;
}
if(DownArrow)
{
DisposeObject(DownArrow);
DownArrow = NULL;
}
if(UpImage)
{
DisposeObject(UpImage);
UpImage = NULL;
}
if(DownImage)
{
DisposeObject(DownImage);
DownImage = NULL;
}
}
/* CreateScroller(LONG Height):
*
* Create scroller and arrow objects.
*/
STATIC BYTE __regargs
CreateScroller(LONG Height)
{
struct DrawInfo *DrawInfo;
BYTE Result = FALSE;
if(DrawInfo = GetScreenDrawInfo(BufferScreen))
{
if(UpImage = (struct Image *)NewObject(NULL,"sysiclass",
SYSIA_Size, SYSISIZE_MEDRES,
SYSIA_Which, UPIMAGE,
SYSIA_DrawInfo, DrawInfo,
TAG_DONE))
{
if(DownImage = (struct Image *)NewObject(NULL,"sysiclass",
SYSIA_Size, SYSISIZE_MEDRES,
SYSIA_Which, DOWNIMAGE,
SYSIA_DrawInfo, DrawInfo,
TAG_DONE))
{
LONG ScrollerHeight,LeftEdge;
ArrowWidth = ARROW_WIDTH;
ArrowHeight = ARROW_HEIGHT;
GetAttr(IA_Height, UpImage,&ArrowHeight);
GetAttr(IA_Width, UpImage,&ArrowWidth);
ScrollerHeight = Height - 2 * ArrowHeight;
LeftEdge = BufferScreen -> Width - ArrowWidth;
if(Scroller = NewObject(NULL,"propgclass",
GA_ID, GAD_SCROLLER,
GA_Top, 0,
GA_Left, LeftEdge,
GA_Width, ArrowWidth,
GA_Height, ScrollerHeight,
GA_Immediate, TRUE,
GA_FollowMouse, TRUE,
GA_RelVerify, TRUE,
PGA_Freedom, FREEVERT,
PGA_NewLook, TRUE,
PGA_Visible, 1,
PGA_Total, 1,
TAG_DONE))
{
STATIC struct TagItem ArrowMappings[] = { GA_ID,GA_ID,TAG_END };
if(UpArrow = NewObject(NULL,"buttongclass",
GA_ID, GAD_UP,
GA_Image, UpImage,
GA_Left, LeftEdge,
GA_Top, ScrollerHeight,
GA_Height, ArrowHeight,
GA_Width, ArrowWidth,
GA_Immediate, TRUE,
GA_RelVerify, TRUE,
GA_Previous, Scroller,
ICA_TARGET, ICTARGET_IDCMP,
ICA_MAP, ArrowMappings,
TAG_DONE))
{
if(DownArrow = NewObject(NULL,"buttongclass",
GA_ID, GAD_DOWN,
GA_Image, DownImage,
GA_Left, LeftEdge,
GA_Top, ScrollerHeight + ArrowHeight,
GA_Height, ArrowHeight,
GA_Width, ArrowWidth,
GA_Immediate, TRUE,
GA_RelVerify, TRUE,
GA_Previous, UpArrow,
ICA_TARGET, ICTARGET_IDCMP,
ICA_MAP, ArrowMappings,
TAG_DONE))
Result = TRUE;
}
}
}
}
FreeScreenDrawInfo(BufferScreen,DrawInfo);
}
if(!Result)
DeleteScroller();
return(Result);
}
/* PrintLine(STRPTR Buffer,LONG LineNumber):
*
* Print a line at a given line number in the displayed area.
*/
STATIC VOID __regargs
PrintLine(STRPTR Buffer,LONG LineNumber)
{
WORD Length = Buffer[-1];
/* Print the text. */
if(Length)
{
Move(BPort,0,BufferLineOffsets[LineNumber] + LocalTextFontBase);
if(Length > NumBufferColumns)
Length = NumBufferColumns;
Text(BPort,Buffer,Length);
}
/* The line doesn't exactly fill the displayed line,
* so erase the remaining columns.
*/
if(Length < BufferLineWidths[LineNumber])
{
SetAPen(BPort,0);
RectFill(BPort,BufferColumnOffsets[Length],BufferLineOffsets[LineNumber],BufferColumnOffsets[BufferLineWidths[LineNumber]] - 1,BufferLineOffsets[LineNumber + 1] - 1);
SetAPen(BPort,1);
}
BufferLineWidths[LineNumber] = Length;
}
/* RedrawScreen(LONG FirstLine):
*
* Redraw the contents of the entire screen and return the
* number of lines actually drawn.
*/
STATIC LONG __regargs
RedrawScreen(LONG FirstLine)
{
LONG i,Last,Line = 0,Result;
ObtainSemaphore(BufferSemaphore);
/* Determine last line to display. */
if((Last = FirstLine + NumBufferLines) >= Lines)
Last = Lines;
Result = Last - FirstLine;
if(Lines)
{
if(LastTopLine != -1)
{
LONG Delta = FirstLine - LastTopLine;
if(ABS(Delta) < NumBufferLines)
{
/* No change? */
if(!Delta)
{
ReleaseSemaphore(BufferSemaphore);
return(Result);
}
else
{
LastTopLine = FirstLine;
/* Scrolled up? */
if(Delta < 0)
{
for(i = NumBufferLines - 1 ; i >= -Delta ; i--)
BufferLineWidths[i] = BufferLineWidths[i + Delta];
ClipBlit(BPort,0,0,BPort,0,BufferLineOffsets[-Delta],BufferColumnOffsets[NumBufferColumns],BufferLineOffsets[NumBufferLines + Delta],MINTERM_COPY);
Last = FirstLine - Delta;
}
else
{
for(i = Delta ; i < NumBufferLines ; i++)
BufferLineWidths[i - Delta] = BufferLineWidths[i];
/* Scrolled down. */
ClipBlit(BPort,0,BufferLineOffsets[Delta],BPort,0,0,BufferColumnOffsets[NumBufferColumns],BufferLineOffsets[NumBufferLines - Delta],MINTERM_COPY);
FirstLine += NumBufferLines - Delta;
Line = NumBufferLines - Delta;
}
}
}
else
LastTopLine = FirstLine;
}
else
LastTopLine = FirstLine;
if(BufferLines)
{
for(i = FirstLine ; i < Last ; i++)
PrintLine(BufferLines[i],Line++);
}
}
ReleaseSemaphore(BufferSemaphore);
/* We didn't fill the whole screen, so clear the rest. */
if(Result < NumBufferLines)
{
WORD i;
for(i = Result ; i < NumBufferLines ; i++)
BufferLineWidths[i] = 0;
SetAPen(BPort,0);
RectFill(BPort,0,BufferLineOffsets[Result],BufferColumnOffsets[NumBufferColumns] - 1,BufferLineOffsets[NumBufferLines] - 1);
SetAPen(BPort,1);
}
return(Result);
}
/* MarkArea(LONG Column,LONG Line,LONG Length):
*
* Mark an area in the term Buffer window.
*/
STATIC VOID __regargs
MarkArea(LONG Column,LONG Line,LONG Length)
{
STATIC LONG OldColumn = -1,OldLine = -1,OldLength = -1;
if(OldColumn != -1)
ClipBlit(BPort,0,0,BPort,BufferColumnOffsets[OldColumn],BufferLineOffsets[OldLine],BufferColumnOffsets[OldLength],LocalTextFontHeight,MINTERM_NOT_C);
if(Column != -1)
{
if(OldColumn != Column || OldLine != Line || OldLength != Length)
ClipBlit(BPort,0,0,BPort,BufferColumnOffsets[Column],BufferLineOffsets[Line],BufferColumnOffsets[Length],LocalTextFontHeight,MINTERM_NOT_C);
}
OldColumn = Column;
OldLine = Line;
OldLength = Length;
}
/* BufferClipPage(struct BlockMarker *Marker):
*
* Send the marked area to the clipboard.
*/
STATIC VOID __inline
BufferClipPage(struct BlockMarker *Marker)
{
if(BufferLines)
{
struct IFFHandle *Handle;
if(Handle = AllocIFF())
{
if(Handle -> iff_Stream = (ULONG)OpenClipboard(Config -> ClipConfig -> ClipboardUnit))
{
InitIFFasClip(Handle);
if(!OpenIFF(Handle,IFFF_WRITE))
{
if(!PushChunk(Handle,ID_FTXT,ID_FORM,IFFSIZE_UNKNOWN))
{
if(!PushChunk(Handle,0,ID_CHRS,IFFSIZE_UNKNOWN))
{
LONG Lines = Marker -> LastLine - Marker -> FirstLine - 1,
i;
if(LINE_WIDTH(BufferLines[Marker -> FirstLine]) > Marker -> FirstColumn)
WriteTrimmedString(Handle,&BufferLines[Marker -> FirstLine][Marker -> FirstColumn],LINE_WIDTH(BufferLines[Marker -> FirstLine]) - Marker -> FirstColumn,NeedClipConversion);
WriteChunkBytes(Handle,"\n",1);
if(Lines > 0)
{
for(i = 0 ; i < Lines ; i++)
{
if(LINE_WIDTH(BufferLines[Marker -> FirstLine + 1 + i]))
WriteTrimmedString(Handle,BufferLines[Marker -> FirstLine + 1 + i],LINE_WIDTH(BufferLines[Marker -> FirstLine + 1 + i]),NeedClipConversion);
WriteChunkBytes(Handle,"\n",1);
}
}
if(Marker -> LastColumn > LINE_WIDTH(BufferLines[Marker -> LastLine]))
WriteTrimmedString(Handle,BufferLines[Marker -> LastLine],LINE_WIDTH(BufferLines[Marker -> LastLine]),NeedClipConversion);
else
WriteTrimmedString(Handle,BufferLines[Marker -> LastLine],Marker -> LastColumn,NeedClipConversion);
WriteChunkBytes(Handle,"\n",1);
PopChunk(Handle);
}
PopChunk(Handle);
}
CloseIFF(Handle);
}
CloseClipboard((struct ClipboardHandle *)Handle -> iff_Stream);
}
FreeIFF(Handle);
}
}
}
/* BufferClip(VOID):
*
* Start buffer marking process.
*/
STATIC VOID
BufferClip(VOID)
{
struct BlockMarker *Marker;
LONG FirstX = BufferWindow -> MouseX / LocalTextFontWidth,
FirstY = BufferWindow -> MouseY / LocalTextFontHeight;
if(Marker = BM_SetMark(BufferWindow -> RPort,ToggleSelect,ToggleSelect,NumBufferColumns,NumBufferLines,0,0,TopLine,Lines,BufferWindow -> MouseX / LocalTextFontWidth,BufferWindow -> MouseY / LocalTextFontHeight,LocalTextFontWidth,LocalTextFontHeight))
{
struct IntuiMessage *Massage;
ULONG Code,IClass;
BYTE Done = FALSE,Aborted = FALSE;
LONG PlusX = LocalTextFontWidth - 1,
MouseX,MouseY,
Delta = 0;
ReportMouse(TRUE,BufferWindow);
while(!Done)
{
WaitPort(BufferWindow -> UserPort);
while(Massage = (struct IntuiMessage *)GetMsg(BufferWindow -> UserPort))
{
IClass = Massage -> Class;
Code = Massage -> Code;
MouseX = Massage -> MouseX;
MouseY = Massage -> MouseY;
ReplyMsg(Massage);
if(IClass == IDCMP_INACTIVEWINDOW)
{
Done = Aborted = TRUE;
break;
}
if(IClass == IDCMP_INTUITICKS && Delta != 0)
{
if(BufferLines)
{
if((Delta > 0 && TopLine + NumBufferLines < Lines) || (Delta < 0 && TopLine > 0))
{
if(Delta < 0)
{
WORD i;
for(i = NumBufferLines - 1 ; i > -Delta ; i--)
BufferLineWidths[i] = BufferLineWidths[i + Delta];
if(DisplayedLines)
ClipBlit(BPort,0,0,BPort,0,LocalTextFontHeight,BufferColumnOffsets[NumBufferColumns],BufferLineOffsets[NumBufferLines - 1],MINTERM_COPY);
BufferLineWidths[0] = NumBufferColumns;
PrintLine(BufferLines[--TopLine],0);
}
else
{
WORD i;
for(i = Delta ; i < NumBufferLines ; i++)
BufferLineWidths[i - Delta] = BufferLineWidths[i];
if(DisplayedLines)
ClipBlit(BPort,0,LocalTextFontHeight,BPort,0,0,BufferColumnOffsets[NumBufferColumns],BufferLineOffsets[NumBufferLines - 1],MINTERM_COPY);
BufferLineWidths[NumBufferLines - 1] = NumBufferColumns;
PrintLine(BufferLines[TopLine + NumBufferLines],NumBufferLines - 1);
TopLine++;
}
Marker -> Top += Delta;
Marker -> LastY -= Delta;
BM_ExtendMark(Marker,(MouseX + PlusX) / LocalTextFontWidth,MouseY / LocalTextFontHeight,Delta);
}
else
Delta = 0;
}
}
if(IClass == IDCMP_MOUSEBUTTONS && (Code & IECODE_UP_PREFIX))
{
BM_Draw(Marker,Marker -> Unselect);
Done = TRUE;
break;
}
if(IClass == IDCMP_MOUSEMOVE)
{
BM_ExtendMark(Marker,(MouseX + PlusX) / LocalTextFontWidth,MouseY / LocalTextFontHeight,0);
if(MouseY < 1)
{
if(TopLine > 0)
Delta = -1;
}
else
{
if(MouseY >= BufferWindow -> Height - 1 && TopLine + NumBufferLines < Lines)
Delta = 1;
}
while(Delta)
{
MouseX = Window -> MouseX;
MouseY = Window -> MouseY;
if((Delta < 0 && MouseY > 0) || (Delta > 0 && MouseY < BufferWindow -> Height - 1))
break;
else
{
if(BufferLines)
{
if((Delta > 0 && TopLine + NumBufferLines < Lines) || (Delta < 0 && TopLine > 0))
{
if(Delta < 0)
{
WORD i;
for(i = NumBufferLines - 1 ; i > -Delta ; i--)
BufferLineWidths[i] = BufferLineWidths[i + Delta];
if(DisplayedLines)
ClipBlit(BPort,0,0,BPort,0,LocalTextFontHeight,BufferColumnOffsets[NumBufferColumns],BufferLineOffsets[NumBufferLines - 1],MINTERM_COPY);
BufferLineWidths[0] = NumBufferColumns;
PrintLine(BufferLines[--TopLine],0);
}
else
{
WORD i;
for(i = Delta ; i < NumBufferLines ; i++)
BufferLineWidths[i - Delta] = BufferLineWidths[i];
if(DisplayedLines)
ClipBlit(BPort,0,LocalTextFontHeight,BPort,0,0,BufferColumnOffsets[NumBufferColumns],BufferLineOffsets[NumBufferLines - 1],MINTERM_COPY);
BufferLineWidths[NumBufferLines - 1] = NumBufferColumns;
PrintLine(BufferLines[TopLine + NumBufferLines],NumBufferLines - 1);
TopLine++;
}
Marker -> Top += Delta;
Marker -> LastY -= Delta;
BM_ExtendMark(Marker,(MouseX + PlusX) / LocalTextFontWidth,MouseY / LocalTextFontHeight,Delta);
SetGadgetAttrs(Scroller,BufferWindow,NULL,
PGA_Top,TopLine,
TAG_DONE);
}
else
break;
}
else
break;
}
}
Delta = 0;
}
}
}
ReportMouse(FALSE,BufferWindow);
while(Massage = (struct IntuiMessage *)GetMsg(BufferWindow -> UserPort))
ReplyMsg(Massage);
if(!Aborted)
{
if(FirstX != BufferWindow -> MouseX / LocalTextFontWidth || FirstY != BufferWindow -> MouseY / LocalTextFontHeight)
{
SetWait(BufferWindow);
if(Marker -> FirstColumn == Marker -> Width)
{
Marker -> FirstLine++;
Marker -> FirstColumn = 0;
}
if(Marker -> LastColumn == 0)
{
Marker -> LastLine--;
Marker -> LastColumn = Marker -> Width;
}
if(Marker -> FirstLine <= Marker -> LastLine)
{
if(Marker -> FirstLine != Marker -> LastLine || Marker -> FirstColumn != Marker -> LastColumn)
{
if(BufferLines)
{
if(Marker -> FirstLine == Marker -> LastLine)
{
if(NeedClipConversion)
{
UBYTE Buffer[256];
LONG Len,i;
STRPTR Dest,
Source = &BufferLines[Marker -> FirstLine][Marker -> FirstColumn];
LONG Size = Marker -> LastColumn - Marker -> FirstColumn;
UBYTE c;
BOOL FirstWrite = TRUE;
do
{
Len = MIN(Size,256);
Size -= Len;
for(i = 0, Dest = Buffer ; i < Len ; i++)
{
if(c = ISOConversion[*Source++])
*Dest++ = c;
else
*Dest++ = ' ';
}
if(Dest > Buffer)
{
if(FirstWrite)
{
FirstWrite = FALSE;
SaveClip(Buffer,(ULONG)Dest - (ULONG)&Buffer[0]);
}
else
AddClip(Buffer,(ULONG)Dest - (ULONG)&Buffer[0]);
}
}
while(Size > 0);
}
else
SaveClip(&BufferLines[Marker -> FirstLine][Marker -> FirstColumn],Marker -> LastColumn - Marker -> FirstColumn);
}
else
BufferClipPage(Marker);
}
}
}
ClrWait(BufferWindow);
}
}
FreeVecPooled(Marker);
}
}
STATIC VOID __regargs
StartSearch(struct SearchInfo *SearchInfo,STRPTR SearchBuffer)
{
LT_LockWindow(BufferWindow);
if(Lines)
{
LONG LineNumber;
ObtainSemaphore(BufferSemaphore);
LineNumber = SearchTextBuffer(SearchInfo);
ReleaseSemaphore(BufferSemaphore);
if(LineNumber == -1)
{
MyEasyRequest(BufferWindow,LocaleString(MSG_TERMBUFFER_DID_NOT_FIND_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),SearchBuffer);
FlushMsg(BufferWindow);
SearchInfo -> FoundY = -1;
MarkArea(-1,-1,-1);
}
else
{
if(LineNumber < TopLine)
{
MarkArea(-1,-1,-1);
DisplayedLines = RedrawScreen(TopLine = LineNumber);
SetGadgetAttrs(Scroller,BufferWindow,NULL,
PGA_Top,TopLine,
TAG_DONE);
}
else
{
if(LineNumber > TopLine + DisplayedLines - 1)
{
MarkArea(-1,-1,-1);
if(LineNumber >= Lines - NumBufferLines)
{
LONG NewCurrentLine;
if((NewCurrentLine = Lines - NumBufferLines) < 0)
NewCurrentLine = 0;
if(TopLine != NewCurrentLine)
DisplayedLines = RedrawScreen(TopLine = NewCurrentLine);
}
else
DisplayedLines = RedrawScreen(TopLine = LineNumber);
SetGadgetAttrs(Scroller,BufferWindow,NULL,
PGA_Top,TopLine,
TAG_DONE);
}
}
MarkArea(SearchInfo -> FoundX,LineNumber - TopLine,SearchInfo -> PatternWidth);
}
}
else
MyEasyRequest(BufferWindow,LocaleString(MSG_GLOBAL_NOTHING_IN_THE_BUFFER_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT));
LT_UnlockWindow(BufferWindow);
}
STATIC VOID __stdargs
BufferDestructor(struct MsgItem *Item)
{
Signal(BufferTask,1L << BufferSignal);
}
STATIC BOOLEAN __regargs
HandleBuffer(LONG TitleOffset)
{
ULONG LastSeconds = 0,
LastMicros = 0,
Seconds,
Micros;
BOOLEAN ClickAndActivate,
UpdatePercent = TRUE;
ULONG SignalSet;
struct IntuiMessage *Massage;
ULONG MsgClass;
UWORD MsgCode,MsgQualifier,LastQualifier = NULL;
WORD MouseX,MouseY;
UBYTE Char,LastChar = 0;
LONG LastWidth = 0;
UBYTE PercentBuffer[80];
UBYTE SearchBuffer[256];
struct TagItem *TagList;
STRPTR PercentTemplate;
BOOLEAN RingBack = FALSE;
struct SearchContext *Context = NULL;
struct SearchInfo *SearchInfo = NULL;
struct Hook HistoryHook;
HistoryHook . h_Data = &TextBufferHistory;
if(LocaleBase)
PercentTemplate = "%lD/%lD (%ld%%)";
else
PercentTemplate = "%ld/%ld (%ld%%)";
do
{
/* Show where we are. */
if(Lines && UpdatePercent)
{
LONG Width,Len;
SetAPen(BufferScreen -> BarLayer -> rp,0);
SetBPen(BufferScreen -> BarLayer -> rp,1);
SetDrMd(BufferScreen -> BarLayer -> rp,JAM2);
SPrintf(PercentBuffer,PercentTemplate,TopLine,Lines > NumBufferLines ? Lines - NumBufferLines : 0,(100 * (TopLine + DisplayedLines)) / Lines);
Len = strlen(PercentBuffer);
Move(BufferScreen -> BarLayer -> rp,TitleOffset,BufferScreen -> BarLayer -> rp -> Font -> tf_Baseline + 1);
Text(BufferScreen -> BarLayer -> rp,PercentBuffer,Len);
Width = TextLength(BufferScreen -> BarLayer -> rp,PercentBuffer,Len);
if(LastWidth > Width)
{
SetAPen(BufferScreen -> BarLayer -> rp,1);
RectFill(BufferScreen -> BarLayer -> rp,TitleOffset + Width,1,TitleOffset + LastWidth - 1,BufferScreen -> BarLayer -> rp -> Font -> tf_YSize);
}
LastWidth = Width;
UpdatePercent = FALSE;
}
SignalSet = Wait(SIG_KILL | SIG_TOFRONT | SIG_UPDATE | SIG_MOVEUP | PORTMASK(BufferWindow -> UserPort));
/* Leave the town? */
if(SignalSet & SIG_KILL)
BufferTerminated = RingBack = TRUE;
/* Bring our window to the front. */
if(SignalSet & SIG_TOFRONT)
{
if(Context)
LT_ShowWindow(Context -> SearchHandle,TRUE);
BumpWindow(BufferWindow);
}
/* We've got one more line in the
* buffer.
*/
if(SignalSet & SIG_UPDATE)
{
if(BufferLines && Lines)
{
if(Lines - TopLine > DisplayedLines && DisplayedLines < NumBufferLines)
{
LONG i = TopLine + DisplayedLines;
do
PrintLine(BufferLines[i++],DisplayedLines++);
while(DisplayedLines < NumBufferLines && i < Lines);
}
}
SetGadgetAttrs(Scroller,BufferWindow,NULL,
PGA_Total, Lines,
PGA_Visible, DisplayedLines,
TAG_DONE);
UpdatePercent = TRUE;
Signal(ThisProcess,SIG_HANDSHAKE);
}
/* The contents of the buffer have moved
* up a line.
*/
if(SignalSet & SIG_MOVEUP)
{
if(TopLine > 0)
{
LastTopLine = --TopLine;
SetGadgetAttrs(Scroller,BufferWindow,NULL,
PGA_Top,TopLine,
TAG_DONE);
}
else
{
LONG i;
MarkArea(-1,-1,-1);
for(i = 0 ; i < NumBufferLines - 1 ; i++)
BufferLineWidths[i] = BufferLineWidths[i + 1];
ClipBlit(BPort,0,BufferLineOffsets[1],BPort,0,0,BufferColumnOffsets[NumBufferColumns],BufferLineOffsets[NumBufferLines - 1],MINTERM_COPY);
PrintLine(BufferLines[NumBufferLines - 1],NumBufferLines - 1);
}
UpdatePercent = TRUE;
Signal(ThisProcess,SIG_HANDSHAKE);
}
/* Process the incoming window
* input.
*/
while(Massage = (struct IntuiMessage *)GetMsg(BufferWindow -> UserPort))
{
if(Context && Context -> SearchWindow == Massage -> IDCMPWindow)
{
MsgClass = NULL;
if(HandleSearchMessage(Context,&Massage))
{
BOOLEAN Ok = Context -> Ok;
DeleteSearchContext(Context);
Context = NULL;
if(Ok)
{
if(SearchInfo)
DeleteSearchInfo(SearchInfo);
if(SearchInfo = CreateSearchInfo(SearchBuffer,SearchForward,IgnoreCase,WholeWords))
StartSearch(SearchInfo,SearchBuffer);
}
else
{
if(SearchInfo)
DeleteSearchInfo(SearchInfo);
SearchInfo = NULL;
}
}
}
else
{
MsgClass = Massage -> Class;
MsgCode = Massage -> Code;
MsgQualifier = Massage -> Qualifier;
MouseX = Massage -> MouseX;
MouseY = Massage -> MouseY;
TagList = (struct TagItem *)Massage -> IAddress;
Seconds = Massage -> Seconds;
Micros = Massage -> Micros;
ClickAndActivate = FALSE;
if(Seconds == LastSeconds && Micros == LastMicros)
{
if(Massage -> Class == IDCMP_ACTIVEWINDOW || Massage -> Class == IDCMP_MOUSEBUTTONS)
ClickAndActivate = TRUE;
}
LastSeconds = Seconds;
LastMicros = Micros;
/* This hack is necessary to obtain the
* character codes generated for the cursor
* keys. A control or alternate qualifier
* would spoil the result (i.e. we would
* not get a valid key code).
*/
Massage -> Qualifier = NULL;
Char = KeyConvert(Massage,NULL,NULL);
/* Just in case anybody needs it... */
Massage -> Qualifier = MsgQualifier;
ReplyMsg((struct Message *)Massage);
}
if(MsgClass == IDCMP_ACTIVEWINDOW)
UpdatePercent = TRUE;
if(MsgClass == IDCMP_IDCMPUPDATE)
{
switch(GetTagData(GA_ID,0,TagList))
{
case GAD_UP:
if(TopLine > 0)
{
TopLine--;
MarkArea(-1,-1,-1);
SetGadgetAttrs(Scroller,BufferWindow,NULL,
PGA_Top,TopLine,
TAG_DONE);
DisplayedLines = RedrawScreen(TopLine);
UpdatePercent = TRUE;
}
break;
case GAD_DOWN:
if(TopLine + NumBufferLines < Lines)
{
TopLine++;
MarkArea(-1,-1,-1);
SetGadgetAttrs(Scroller,BufferWindow,NULL,
PGA_Top,TopLine,
TAG_DONE);
DisplayedLines = RedrawScreen(TopLine);
UpdatePercent = TRUE;
}
break;
}
}
if(MsgClass == IDCMP_MOUSEMOVE || MsgClass == IDCMP_GADGETDOWN || MsgClass == IDCMP_GADGETUP)
{
LONG Position;
GetAttr(PGA_Top,Scroller,(ULONG *)&Position);
if(Position != TopLine)
{
MarkArea(-1,-1,-1);
DisplayedLines = RedrawScreen(TopLine = Position);
UpdatePercent = TRUE;
}
}
if(MsgClass == IDCMP_RAWKEY)
{
if(MsgCode == HELP_CODE)
GuideDisplay(CONTEXT_TEXTBUFFER);
if(LastChar)
{
if((MsgCode & IECODE_UP_PREFIX) || !(LastQualifier & IEQUALIFIER_REPEAT))
{
SetGadgetAttrs(Scroller,BufferWindow,NULL,
PGA_Top,TopLine,
TAG_DONE);
UpdatePercent = TRUE;
}
}
if(LastChar = Char)
{
/* Use the numeric keypad keys to
* move through the buffer.
*/
if(MsgQualifier & IEQUALIFIER_NUMERICPAD)
{
/* Remove the numpad qualifier. */
MsgQualifier &= ~IEQUALIFIER_NUMERICPAD;
switch(Char - '0')
{
/* Jump to bottom. */
case 1: Char = CDN;
MsgQualifier |= IEQUALIFIER_CONTROL;
break;
/* Jump to top. */
case 7: Char = CUP;
MsgQualifier |= IEQUALIFIER_CONTROL;
break;
/* Move one page down. */
case 3: Char = CDN;
MsgQualifier |= IEQUALIFIER_LSHIFT;
break;
/* Move one page up. */
case 9: Char = CUP;
MsgQualifier |= IEQUALIFIER_LSHIFT;
break;
/* Move one line down. */
case 2: Char = CDN;
break;
/* Move one line up. */
case 8: Char = CUP;
break;
}
}
/* Check cursor keys. */
switch(Char)
{
/* Scroll the buffer up. */
case CUP:
if(MsgQualifier & (IEQUALIFIER_CONTROL | IEQUALIFIER_LALT | IEQUALIFIER_RALT))
{
MarkArea(-1,-1,-1);
if(TopLine)
{
DisplayedLines = RedrawScreen(0);
TopLine = 0;
LastChar = 0;
SetGadgetAttrs(Scroller,BufferWindow,NULL,
PGA_Top,TopLine,
TAG_DONE);
UpdatePercent = TRUE;
}
break;
}
if(MsgQualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
{
LONG NewCurrentLine;
if((NewCurrentLine = TopLine - NumBufferLines) < 0)
NewCurrentLine = 0;
MarkArea(-1,-1,-1);
if(NewCurrentLine != TopLine)
{
DisplayedLines = RedrawScreen(NewCurrentLine);
TopLine = NewCurrentLine;
LastChar = 0;
SetGadgetAttrs(Scroller,BufferWindow,NULL,
PGA_Top,TopLine,
TAG_DONE);
UpdatePercent = TRUE;
}
break;
}
if(TopLine)
{
MarkArea(-1,-1,-1);
DisplayedLines = RedrawScreen(--TopLine);
UpdatePercent = TRUE;
}
break;
/* Scroll the buffer down. */
case CDN:
if(MsgQualifier & (IEQUALIFIER_CONTROL | IEQUALIFIER_LALT | IEQUALIFIER_RALT))
{
LONG NewCurrentLine;
if((NewCurrentLine = Lines - NumBufferLines) < 0)
NewCurrentLine = 0;
MarkArea(-1,-1,-1);
if(TopLine != NewCurrentLine)
{
DisplayedLines = RedrawScreen(NewCurrentLine);
TopLine = NewCurrentLine;
LastChar = 0;
SetGadgetAttrs(Scroller,BufferWindow,NULL,
PGA_Top,TopLine,
TAG_DONE);
UpdatePercent = TRUE;
}
break;
}
if(MsgQualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
{
LONG NewCurrentLine;
if((NewCurrentLine = TopLine + (2 * NumBufferLines)) > Lines)
NewCurrentLine = Lines;
if((NewCurrentLine = NewCurrentLine - NumBufferLines) < 0)
NewCurrentLine = 0;
MarkArea(-1,-1,-1);
if(NewCurrentLine != TopLine)
{
DisplayedLines = RedrawScreen(NewCurrentLine);
TopLine = NewCurrentLine;
LastChar = 0;
SetGadgetAttrs(Scroller,BufferWindow,NULL,
PGA_Top,TopLine,
TAG_DONE);
UpdatePercent = TRUE;
}
break;
}
if(TopLine + NumBufferLines < Lines)
{
MarkArea(-1,-1,-1);
DisplayedLines = RedrawScreen(TopLine + 1);
TopLine++;
UpdatePercent = TRUE;
}
break;
}
LastQualifier = MsgQualifier;
}
else
LastQualifier = NULL;
continue;
}
/* User hit a mouse button. */
if(MsgClass == IDCMP_MOUSEBUTTONS && (!ClickAndActivate || MsgCode != SELECTDOWN) && !(MsgCode & IECODE_UP_PREFIX))
{
MarkArea(-1,-1,-1);
/* Reasonable dimensions? */
if(MouseY / LocalTextFontHeight < DisplayedLines && MouseX / LocalTextFontWidth < NumBufferColumns)
{
ObtainSemaphore(BufferSemaphore);
BufferClip();
UpdatePercent = TRUE;
LastTopLine = TopLine;
ReleaseSemaphore(BufferSemaphore);
if(MsgQualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
{
struct DataMsg Msg;
InitMsgItem(&Msg,BufferDestructor);
Msg . Type = DATAMSGTYPE_WRITECLIP;
Msg . Size = Config -> ClipConfig -> ClipboardUnit;
Forbid();
ClrSignal(1L << BufferSignal);
PutMsgItem(SpecialQueue,(struct MsgItem *)&Msg);
Wait(1L << BufferSignal);
Permit();
}
break;
}
}
if(MsgClass == IDCMP_MENUHELP)
GuideDisplay(CONTEXT_BUFFER_MENU);
if(MsgClass == IDCMP_MENUPICK)
{
struct MenuItem *MenuItem;
while(MsgCode != MENUNULL)
{
if(MenuItem = ItemAddress(BufferMenuStrip,MsgCode))
{
switch((ULONG)GTMENUITEM_USERDATA(MenuItem))
{
case MEN_SEARCH:
if(Context)
LT_ShowWindow(Context -> SearchHandle,TRUE);
else
Context = CreateSearchContext(BufferWindow,SearchBuffer,&HistoryHook,&SearchForward,&IgnoreCase,&WholeWords);
UpdatePercent = TRUE;
break;
case MEN_REPEAT:
if(Context)
LT_ShowWindow(Context -> SearchHandle,TRUE);
else
{
if(SearchInfo)
StartSearch(SearchInfo,SearchBuffer);
else
Context = CreateSearchContext(BufferWindow,SearchBuffer,&HistoryHook,&SearchForward,&IgnoreCase,&WholeWords);
}
UpdatePercent = TRUE;
break;
case MEN_GOTO:
if(Window)
BumpWindow(Window);
break;
case MEN_QUITBUF:
BufferTerminated = TRUE;
break;
case MEN_CLEARBUF_CONTENTS:
if(Lines)
{
UpdatePercent = TRUE;
LT_LockWindow(BufferWindow);
if(MsgQualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
{
FreeBuffer();
LT_UnlockWindow(BufferWindow);
FlushMsg(BufferWindow);
DisplayedLines = RedrawScreen(TopLine = 0);
SetGadgetAttrs(Scroller,BufferWindow,NULL,
PGA_Top, TopLine,
PGA_Total, Lines,
PGA_Visible, NumBufferLines,
TAG_DONE);
break;
}
else
{
if(Config -> MiscConfig -> ProtectiveMode)
{
if(!MyEasyRequest(BufferWindow,LocaleString(MSG_TERMBUFFER_BUFFER_STILL_HOLDS_LINES_TXT),LocaleString(MSG_GLOBAL_YES_NO_TXT),Lines))
{
LT_UnlockWindow(BufferWindow);
break;
}
}
FreeBuffer();
LT_UnlockWindow(BufferWindow);
FlushMsg(BufferWindow);
DisplayedLines = RedrawScreen(TopLine = 0);
SetGadgetAttrs(Scroller,BufferWindow,NULL,
PGA_Top, TopLine,
PGA_Total, Lines,
PGA_Visible, NumBufferLines,
TAG_DONE);
break;
}
LT_UnlockWindow(BufferWindow);
FlushMsg(BufferWindow);
}
break;
}
MsgCode = MenuItem -> NextSelect;
}
else
break;
}
}
}
}
while(!BufferTerminated);
if(Context)
DeleteSearchContext(Context);
if(SearchInfo)
DeleteSearchInfo(SearchInfo);
return(RingBack);
}
/* BufferServer():
*
* Asynchronous task to display the data stored in the
* scrollback display buffer.
*/
STATIC VOID __saveds
BufferServer(VOID)
{
BOOLEAN Defaults;
struct ColorSpec ColorSpec[3];
LONG Width,Height;
ULONG DisplayMode;
struct Rectangle DisplayClip;
struct DimensionInfo DimensionInfo;
struct TextFont *LocalFont;
struct Task *Father;
BOOLEAN RingBack = TRUE;
Father = (struct Task *)SysBase -> ThisTask -> tc_UserData;
memcpy(&LocalTextFont,&TextAttr,sizeof(struct TTextAttr));
LocalTextFont . tta_Name = LocalTextFontName;
LocalTextFont . tta_YSize = Config -> TerminalConfig -> TextFontHeight;
strcpy(LocalTextFontName,Config -> TerminalConfig -> TextFontName);
memcpy(&LocalUserFont,&UserFont,sizeof(struct TTextAttr));
LocalUserFont . tta_Name = LocalUserFontName;
strcpy(LocalUserFontName,UserFont . tta_Name);
if(!Config -> CaptureConfig -> ConvertChars && Config -> TerminalConfig -> FontMode != FONT_STANDARD)
{
strcpy(LocalTextFontName,Config -> TerminalConfig -> IBMFontName);
LocalTextFont . tta_YSize = Config -> TerminalConfig -> IBMFontHeight;
NeedClipConversion = TRUE;
}
else
NeedClipConversion = FALSE;
if(LocalFont = OpenDiskFont(&LocalTextFont))
{
LocalTextFontBase = LocalFont -> tf_Baseline;
LocalTextFontWidth = LocalFont -> tf_XSize;
LocalTextFontHeight = LocalTextFont . tta_YSize;
CloseFont(LocalFont);
}
/* Reset top line index. */
LastTopLine = -1;
/* Up and running... */
BufferTerminated = FALSE;
Forbid();
if(Window && DrawInfo)
{
UWORD Colour;
/* Set up the startup colours for our buffer screen. */
ColorSpec[0] . ColorIndex = 0;
Colour = GetRGB4(Window -> WScreen -> ViewPort . ColorMap,DrawInfo -> dri_Pens[BACKGROUNDPEN]);
ColorSpec[0] . Red = (Colour >> 8) & 0xF;
ColorSpec[0] . Green = (Colour >> 4) & 0xF;
ColorSpec[0] . Blue = (Colour ) & 0xF;
ColorSpec[1] . ColorIndex = 1;
Colour = GetRGB4(Window -> WScreen -> ViewPort . ColorMap,DrawInfo -> dri_Pens[TEXTPEN]);
ColorSpec[1] . Red = (Colour >> 8) & 0xF;
ColorSpec[1] . Green = (Colour >> 4) & 0xF;
ColorSpec[1] . Blue = (Colour ) & 0xF;
ColorSpec[2] . ColorIndex = -1;
Defaults = FALSE;
}
else
Defaults = TRUE;
Permit();
/* We'll use a fixed screen width, only the
* height is adapted from the main screen.
*/
DisplayMode = Config -> CaptureConfig -> BufferScreenMode;
if(ModeNotAvailable(DisplayMode))
DisplayMode = Config -> ScreenConfig -> DisplayMode;
if(ModeNotAvailable(DisplayMode))
{
struct Screen *PubScreen = LockPubScreen(NULL);
if(PubScreen)
{
DisplayMode = GetVPModeID(&PubScreen -> ViewPort);
UnlockPubScreen(NULL,PubScreen);
}
else
DisplayMode = DEFAULT_MONITOR_ID | HIRES_KEY;
}
/* Set up the actual width of the screen we want. */
Width = Config -> CaptureConfig -> BufferWidth * LocalTextFontWidth + ArrowWidth + 1;
if((BufferSignal = AllocSignal(-1)) != -1)
{
/* Get the mode dimension info. */
if(GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(struct DimensionInfo),DTAG_DIMS,DisplayMode))
{
/* Determine maximum text overscan width. */
LONG TextWidth = DimensionInfo . TxtOScan . MaxX - DimensionInfo . TxtOScan . MinX + 1;
/* Too small? */
if(Width < DimensionInfo . MinRasterWidth)
Width = DimensionInfo . MinRasterWidth;
/* Far too large? */
if(Width > DimensionInfo . MaxRasterWidth)
Width = DimensionInfo . MaxRasterWidth;
/* A bit too large? */
if(Width > TextWidth)
Width = TextWidth;
if(LocalFont = OpenDiskFont(&LocalTextFont))
{
/* Inquire the text overscan dimensions. */
if(QueryOverscan(DisplayMode,&DisplayClip,OSCAN_TEXT))
{
/* Centre the buffer screen. */
if(DisplayClip . MaxX - DisplayClip . MinX + 1 > Width)
{
LONG Differ = (DisplayClip . MaxX - DisplayClip . MinX + 1 - Width) / 2;
switch(Config -> CaptureConfig -> BufferScreenPosition)
{
case SCREEN_LEFT:
DisplayClip . MaxX = DisplayClip . MinX + Width;
break;
case SCREEN_RIGHT:
DisplayClip . MinX = DisplayClip . MaxX - Width;
break;
case SCREEN_CENTRE:
DisplayClip . MinX += Differ;
DisplayClip . MaxX -= Differ;
break;
}
}
/* Open a single bitplane clone of the main screen. */
if(BufferScreen = (struct Screen *)OpenScreenTags(NULL,
SA_Title, LocaleString(MSG_TERMBUFFER_TERM_BUFFER_TXT),
SA_Depth, 1,
SA_Left, DisplayClip . MinX,
SA_DClip, &DisplayClip,
SA_DisplayID, DisplayMode,
SA_Font, &LocalUserFont,
SA_Behind, TRUE,
SA_AutoScroll, TRUE,
Defaults ? TAG_IGNORE : SA_Colors,ColorSpec,
TAG_END))
{
if(BufferVisualInfo = GetVisualInfo(BufferScreen,TAG_DONE))
{
LocalizeMenu(BufferMenu,MSG_TERMBUFFER_PROJECT_MEN);
if(BufferMenuStrip = CreateMenus(BufferMenu,TAG_DONE))
{
if(BufferDrawInfo = GetScreenDrawInfo(BufferScreen))
{
if(!CreateMenuGlyphs(BufferScreen,BufferDrawInfo,&BufferAmigaGlyph,&BufferCheckGlyph))
{
FreeScreenDrawInfo(BufferScreen,BufferDrawInfo);
BufferDrawInfo = NULL;
}
}
if(LayoutMenus(BufferMenuStrip,BufferVisualInfo,
BufferAmigaGlyph ? GTMN_AmigaKey : TAG_IGNORE, BufferAmigaGlyph,
BufferCheckGlyph ? GTMN_Checkmark : TAG_IGNORE, BufferCheckGlyph,
GTMN_TextAttr, &LocalUserFont,
GTMN_NewLookMenus, TRUE,
TAG_DONE))
{
Height = (BufferScreen -> Height - (BufferScreen -> BarHeight + 2)) / LocalTextFontHeight;
/* Open a cute window on our buffer screen. */
if(BufferWindow = OpenWindowTags(NULL,
WA_Top, BufferScreen -> BarHeight + 2,
WA_Left, 0,
WA_Width, BufferScreen -> Width,
WA_Height, Height * LocalTextFontHeight,
WA_Backdrop, TRUE,
WA_Borderless, TRUE,
WA_SmartRefresh,FALSE,
WA_CustomScreen,BufferScreen,
WA_RMBTrap, TRUE,
WA_NewLookMenus,TRUE,
WA_RptQueue, 1,
WA_IDCMP, IDCMP_IDCMPUPDATE | IDCMP_RAWKEY | IDCMP_INACTIVEWINDOW | IDCMP_ACTIVEWINDOW | IDCMP_MOUSEBUTTONS | IDCMP_MENUPICK | IDCMP_GADGETUP | IDCMP_GADGETDOWN | IDCMP_MOUSEMOVE | IDCMP_MENUHELP,
WA_MenuHelp, TRUE,
BufferAmigaGlyph ? WA_AmigaKey : TAG_IGNORE, BufferAmigaGlyph,
BufferCheckGlyph ? WA_Checkmark : TAG_IGNORE, BufferCheckGlyph,
TAG_DONE))
{
if(BufferLineWidths = (UWORD *)AllocVecPooled(2 * sizeof(UWORD) * (BufferWindow -> Height / LocalTextFontHeight + 1) + sizeof(UWORD) * (BufferWindow -> Width / LocalTextFontWidth + 1),MEMF_ANY | MEMF_CLEAR))
{
UWORD Index;
WORD i;
BufferLineOffsets = &BufferLineWidths[BufferWindow -> Height / LocalTextFontHeight + 1];
BufferColumnOffsets = &BufferLineOffsets[BufferWindow -> Height / LocalTextFontHeight + 1];
for(i = Index = 0 ; i < BufferWindow -> Height / LocalTextFontHeight + 1 ; i++)
{
BufferLineOffsets[i] = Index;
Index += LocalTextFontHeight;
}
for(i = Index = 0 ; i < BufferWindow -> Width / LocalTextFontWidth + 1 ; i++)
{
BufferColumnOffsets[i] = Index;
Index += LocalTextFontWidth;
}
if(CreateScroller(BufferWindow -> Height))
{
ObtainSemaphore(&BufferTaskSemaphore);
BufferTask = SysBase -> ThisTask;
ReleaseSemaphore(&BufferTaskSemaphore);
/* Signal our father process that
* we're running.
*/
Signal(Father,SIG_HANDSHAKE);
Father = NULL;
SetMenuStrip(BufferWindow,BufferMenuStrip);
AddGList(BufferWindow,Scroller,(UWORD)-1,(UWORD)-1,NULL);
RefreshGList(Scroller,BufferWindow,NULL,(UWORD)-1);
/* Determine maximum dimensions of
* the buffer screen (in rows and
* columns).
*/
NumBufferColumns = (BufferWindow -> Width - (ArrowWidth + 1)) / LocalTextFontWidth;
NumBufferLines = BufferWindow -> Height / LocalTextFontHeight;
if(TopLine == -1 || !Config -> CaptureConfig -> RememberBufferScreen)
{
switch(Config -> CaptureConfig -> OpenBufferScreen)
{
case BUFFER_TOP:
TopLine = 0;
break;
case BUFFER_END:
if((TopLine = Lines - NumBufferLines) < 0)
TopLine = 0;
break;
default:
TopLine = 0;
break;
}
}
if(TopLine > Lines - NumBufferLines)
TopLine = 0;
BPort = BufferWindow -> RPort;
SetFont(BPort,LocalFont);
/* Bring the screen to the front. */
BumpWindow(BufferWindow);
/* Set the drawing pens for the window. */
SetAPen(BPort,1);
SetBPen(BPort,0);
SetDrMd(BPort,JAM2);
/* Initial creation of the buffer display. */
DisplayedLines = RedrawScreen(TopLine);
SetGadgetAttrs(Scroller,BufferWindow,NULL,
PGA_Top, TopLine,
PGA_Total, Lines,
PGA_Visible, NumBufferLines,
TAG_DONE);
BufferWindow -> Flags &= ~WFLG_RMBTRAP;
RingBack = HandleBuffer(TextLength(BufferScreen -> BarLayer -> rp,LocaleString(MSG_TERMBUFFER_TERM_BUFFER_TXT),strlen(LocaleString(MSG_TERMBUFFER_TERM_BUFFER_TXT))) + TextLength(BufferScreen -> BarLayer -> rp," ",1) + 4);
RemoveGList(BufferWindow,Scroller,(UWORD)-1);
DeleteScroller();
}
FreeVecPooled(BufferLineWidths);
}
if(Window)
BumpWindow(Window);
MarkArea(-1,-1,-1);
ScreenToBack(BufferScreen);
BufferWindow -> Flags |= WFLG_RMBTRAP;
ClearMenuStrip(BufferWindow);
LT_DeleteWindowLock(BufferWindow);
CloseWindow(BufferWindow);
}
}
DisposeObject(BufferAmigaGlyph);
DisposeObject(BufferCheckGlyph);
FreeScreenDrawInfo(BufferScreen,BufferDrawInfo);
FreeMenus(BufferMenuStrip);
}
FreeVisualInfo(BufferVisualInfo);
}
CloseScreen(BufferScreen);
}
}
CloseFont(LocalFont);
}
}
FreeSignal(BufferSignal);
}
ObtainSemaphore(&BufferTaskSemaphore);
BufferTask = NULL;
ReleaseSemaphore(&BufferTaskSemaphore);
Forbid();
if(RingBack)
{
if(Father)
Signal(Father,SIG_HANDSHAKE);
else
Signal(ThisProcess,SIG_HANDSHAKE);
}
}
/* LaunchBuffer():
*
* Launch the buffer process.
*/
BYTE
LaunchBuffer()
{
ObtainSemaphore(&BufferTaskSemaphore);
/* Is the buffer process already running? */
if(BufferTask)
{
/* Tell it to bring its screen to the front. */
Signal(BufferTask,SIG_TOFRONT);
ReleaseSemaphore(&BufferTaskSemaphore);
/* Return success. */
return(TRUE);
}
else
{
struct Task *Child;
BYTE Result = FALSE;
ReleaseSemaphore(&BufferTaskSemaphore);
Forbid();
/* Launch the buffer process. */
if(Child = (struct Task *)CreateNewProcTags(
NP_Entry, BufferServer,
NP_Name, "term Buffer Process",
NP_Priority, SysBase -> ThisTask -> tc_Node . ln_Pri,
NP_StackSize, 4000,
NP_WindowPtr, -1,
TAG_END))
{
Child -> tc_UserData = SysBase -> ThisTask;
ClrSignal(SIG_HANDSHAKE);
Wait(SIG_HANDSHAKE);
ObtainSemaphore(&BufferTaskSemaphore);
if(BufferTask)
Result = TRUE;
ReleaseSemaphore(&BufferTaskSemaphore);
}
Permit();
/* Return the result. */
return(Result);
}
}
/* TerminateBuffer():
*
* Terminate the buffer process.
*/
VOID
TerminateBuffer()
{
ObtainSemaphore(&BufferTaskSemaphore);
if(BufferTask)
{
Forbid();
Signal(BufferTask,SIG_KILL);
ReleaseSemaphore(&BufferTaskSemaphore);
ClrSignal(SIG_HANDSHAKE);
Wait(SIG_HANDSHAKE);
Permit();
}
else
ReleaseSemaphore(&BufferTaskSemaphore);
LastTopLine = -1;
}